package airacrobats.io;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;

/**
 * Class that loads data files. It uses persistent loading. This means that it
 * keeps the data file opened and reads object by object of it until no more objects are found.
 * When it happens, the class closes the stream and returns a null object.
 */
public abstract class DataLoader<T> extends Loader<T>
{
    /**
     * Data input stream.
     */
    private DataInputStream dataInputStream;
    /**
     * Stream file path.
     */
    private String streamFile;
    /**
     * Flag indicating if the stream is closed.
     */
    private boolean closed;
    
    /**
     */
    protected T load(String file) throws IOException
    {
        // Checks if the current stream of the loader is different from the new one.
        if (!file.equals(streamFile))
        {
            // Note that the current stream is (should be) closed. Here, it opens the new stream.
            streamFile = file;
            dataInputStream = new DataInputStream(new FileInputStream(new File(file)));
            closed = false;
        }

        T t = null;
        if (closed)
            return t;

        t = load(dataInputStream);

        // Checks if the stream has reached the end of the file, so it can be closed.
        if (dataInputStream.available() == 0)
        {
            dataInputStream.close();
            closed = true;
        }

        return t;
    }

    /**
     * Reads a string of the data file.
     * @return The string read.
     * @throws IOException Thrown if an I/O error happens.
     */
    protected String readString() throws IOException
    {
        int length = dataInputStream.readChar();
        byte[] buffer = new byte[length];
        dataInputStream.read(buffer);
        return new String(buffer, Charset.forName("UTF-8"));
    }

    /**
     * Loads the data file.
     * @param dataInputStream The file stream.
     * @return The next object of the data file.
     * @throws IOException Thrown if an I/O error occurs.
     */
    protected abstract T load(DataInputStream dataInputStream) throws IOException;
}
